package com.emm.yixun.website.listeners;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;

import com.emm.yixun.common.model.enums.*;
import com.emm.yixun.customer.service.channel.ChannelSendHttpMessageService;
import com.emm.yixun.website.service.pmo.PmoPushService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.emm.yixun.common.enums.ResponseEnums;
import com.emm.yixun.common.model.BusinessAbnorma;
import com.emm.yixun.common.model.Customer;
import com.emm.yixun.common.model.HaveReceiveRefund;
import com.emm.yixun.common.model.NeedReceiveRefund;
import com.emm.yixun.common.model.PayDeposit;
import com.emm.yixun.common.model.ProjectRoom;
import com.emm.yixun.common.model.Signed;
import com.emm.yixun.common.model.Subscribe;
import com.emm.yixun.common.model.dto.BusinessAbnormaDto;
import com.emm.yixun.common.model.dto.CustomerDto;
import com.emm.yixun.common.model.dto.HaveReceiveRefundDto;
import com.emm.yixun.common.model.dto.MortgageRecordDto;
import com.emm.yixun.common.model.dto.NeedReceiveRefundDto;
import com.emm.yixun.common.model.dto.NoticeEntity;
import com.emm.yixun.common.model.dto.PayDepositDto;
import com.emm.yixun.common.model.dto.ProjectRoomDto;
import com.emm.yixun.common.model.dto.RoomChangeHistoryDto;
import com.emm.yixun.common.model.dto.SignedDto;
import com.emm.yixun.common.model.dto.SubscribeDto;
import com.emm.yixun.common.response.Response;
import com.emm.yixun.common.response.ResponseList;
import com.emm.yixun.common.utils.BeanUtil;
import com.emm.yixun.common.utils.DateStyle;
import com.emm.yixun.common.utils.DateUtils;
import com.emm.yixun.customer.service.CustomerServiceFacade;
import com.emm.yixun.customer.service.PayDepositServiceFacade;
import com.emm.yixun.customer.service.SignedServiceFacade;
import com.emm.yixun.customer.service.SubscribeServiceFacade;
import com.emm.yixun.estate.service.ProjectRoomServiceFacade;
import com.emm.yixun.marketing.service.BusinessAbnormaServiceFacade;
import com.emm.yixun.marketing.service.HaveReceiveRefundServiceFacade;
import com.emm.yixun.marketing.service.MortgageRecordServiceFacade;
import com.emm.yixun.marketing.service.NeedReceiveRefundServiceFacade;
import com.emm.yixun.marketing.service.RoomChangeHistoryServiceFacade;
import com.emm.yixun.system.service.notice.signed.SignedChangeHouseNoticeFacade;
import com.emm.yixun.website.common.utils.SpringWebContextUtil;
import com.emm.yixun.website.service.ActivitiProcessServiceImpl;
import com.emm.yixun.website.service.pmo.LevelProjectDataService;
import com.emm.yixun.website.service.system.log.ActCommitLogService;
/**
* 类描述： 签约换房流程审批结果处理
* 创建者： ThinkPad
* 项目名称： emm-website
* 创建时间： 2016年7月12日 下午1:59:03
* 版本号： v1.0
 */
public class SignedRoomChangeListeners implements Serializable, ExecutionListener{
	private static final long serialVersionUID = -2409351825760552344L;
	
	@Override
	public void notify(DelegateExecution execution) throws Exception {
		String id=execution.getProcessBusinessKey(); //业务ID
		String processInstanceId=execution.getProcessInstanceId();	//流程ID
		Long businessId = null;
		BusinessAbnorma ba = businessById(new Long(id)); //异常流程ID
		if(null != ba) {
			businessId = ba.getId();
		}
		
		Response<Signed> responseNew=getSignedServiceFacade().findById(Long.valueOf(id));
		Signed newSigned=responseNew.getEntity();
		if(null==newSigned){
			throw new RuntimeException("签约换房业务重新发起的签约不存在");
		}
		
		Long oldSignedId = newSigned.getOldSignedId();
		//当新签约异常流程ID为空时，使用原签约ID获取
		if(businessId == null){
			ba = businessById(oldSignedId); //异常流程ID
			businessId = ba.getId();
		}
		Response<Signed> responseOld=getSignedServiceFacade().findById(oldSignedId);
		Signed oldSigned=responseOld.getEntity();
		if(null==oldSigned){
			throw new RuntimeException("签约换房业务原签约记录不存在");
		}
		//原签约房间
		Response<ProjectRoom> queryRoom = getProjectRoomServiceFacade().findById(oldSigned.getRoomId());
		ProjectRoom oldRoom=queryRoom.getEntity();
		if(getActivitiProcessServiceImpl().isCheckPass(processInstanceId)){
			
			boolean flag = checkAuditCommit(ba);
			if(!flag) {
				throw new Exception(ResponseEnums.RESPONSEENUMS_999999.getName());
			}
			
			/**
			 * 1.原签约记录第二业务状态已换房
			 * 2.原签约对应房源状态变更和新增变更记录
			 * 3.复制原签约记录，将第一和第二业务状态更新为已换房 
			 * 4.新增新签约待收款记录
			 * 5.针对复制的签约记录生成应退和实退记录
			 * 6.增加新签约已收款记录
			 * 7.更改客户状态
			 * 8.更改新签约记录的审核状态为已通过
			 * 9.发送通知
			 */
			
			
			//修改流程状态为审核通过
			if(businessId!=null){
				//修改
				BusinessAbnormaDto updateAbnorma= new BusinessAbnormaDto();
				updateAbnorma.setId(businessId);
				updateAbnorma.setAuditStatus(AuditStatusEnum.SUCCESS.getNo());
				updateAbnorma.setCheckDate(Calendar.getInstance().getTime()); //审核时间
				getbusinessAbnormaServiceFacade().updateByPrimaryKey(updateAbnorma, true);
			}
			
			//1.原签约记录第二业务状态已换房
			updateBusinessSecStatus(oldSignedId);
			
			//2.原签约对应房源状态变更和新增变更记录
			updateRoomStaus(oldSigned);
			addRoomChangeHistory(oldSigned,oldRoom,newSigned.getId());
			
			//3.复制原签约记录，将第一和第二业务状态更新为已换房 
			SignedDto copySigned=copyOldSigned(oldSigned);
			
			//4.新增新签约待收款记录
			handleNewSigned(newSigned);
			
			//查询签约已收款
			ResponseList<HaveReceiveRefund> havResponseList = getOldHaveReceiveRefund(oldSigned.getId());
			if(havResponseList.isSuccess() && null!=havResponseList.getEntity()){
				//5.复制的签约记录生成应退和实退记录
				handleOldSignedMoney(havResponseList, copySigned);
				
				//6 增加新签约的收款记录
				calculationNewHaveReceive(havResponseList, newSigned.getId());
			}
			
			//修改原签约未收款为已结清
			setOldNeedStatus(oldSigned.getId());
			
			//7.更改客户状态
			changeCustomerStatus(newSigned.getCustomerId());
			
			//8.更改新签约记录的审核状态为已通过
			updateNewSingedAuditStatus(Long.parseLong(id));
			
			//9.添加推送PMO待推送记录
			String pmoProjectCode = getLevelProjectDataService().getProjectPmoCode(oldSigned.getProjectId());
			String pushMonth = DateUtils.formatDate(new Date(), DateStyle.YYYYMM.getValue());
			PmoPushService pmoPushService = getPmoPushService();
			pmoPushService.addPmoPushData(oldSigned.getProjectId(), pmoProjectCode, pushMonth, processInstanceId, "换房");
			
			//10.退原认购记录
			subscribeRetreat(oldSigned.getRoomId(), oldSigned.getCustomerId());
			/**
			 * 推送到渠道
			 */
			getChannelSendHttpMessageService().sendTransaction(Long.parseLong(id), TransTypeEnum.SIGNED.getNo(), false);
		}else{
			
			boolean flag = checkAuditCommit(ba);
			if(!flag) {
				throw new Exception(ResponseEnums.RESPONSEENUMS_999999.getName());
			}
			
			//审核不通过
			/**
			 * 1.删除新签约记录（20171013暂定审核未通过的解决方案）
			 * 2.修改新签约房间状态为可售
			 */
			if(businessId!=null){
				BusinessAbnormaDto updateAbnorma= new BusinessAbnormaDto();
				updateAbnorma.setId(businessId);
				updateAbnorma.setAuditStatus(AuditStatusEnum.REJECT.getNo());
				getbusinessAbnormaServiceFacade().updateByPrimaryKey(updateAbnorma, true);
			}
			
			//1.删除新签约记录
			getSignedServiceFacade().deleteByPrimaryKey(newSigned.getId());
			
			//2.修改新签约房间状态为可售
			ProjectRoomDto projectRoomDto = new ProjectRoomDto();
			projectRoomDto.setId(newSigned.getRoomId());
			projectRoomDto.setRoomStatus(RoomStatusEnum.VENDIBILITY.getNo());//可售
			Response<Integer> responseRoomDto=getProjectRoomServiceFacade().updateByPrimaryKey(projectRoomDto, true);
			if(!responseRoomDto.isSuccess()){
				throw new Exception("房间状态为可售出错");
			}
		}
		//9.发送通知
		notice(oldSignedId,processInstanceId);
	}
	
	private void updateBusinessSecStatus(Long signedId){
		SignedDto signedDto = new SignedDto();
		signedDto.setId(signedId);
		signedDto.setBusinessSecStatus(BusinessStatusEnum.HAVEWARDS.getNo());
		Response<Integer> updateResponse=getSignedServiceFacade().updateByPrimaryKey(signedDto, true);
		if(!updateResponse.isSuccess()){
			throw new RuntimeException(updateResponse.getResultMessage());
		}
	}
	
	//变更原签约房间状态
	private void updateRoomStaus(Signed oldSigned){
		
		//判断是否还有审核中或者审核通过的数据，以此来判断是否返回到可售
		PayDepositDto payDepositDto = new PayDepositDto();
		payDepositDto.setM_auditStatus(" and t.audit_status in (1,3) and t.business_status in (1,4)");
		payDepositDto.setRoomId(oldSigned.getRoomId());
		ResponseList<PayDeposit> responsePDList = getPayDepositServiceFacade().findByDtoJ(payDepositDto);
		
		ProjectRoomDto roomUpdateDto = new ProjectRoomDto(); 
		roomUpdateDto.setId(oldSigned.getRoomId());
		if(responsePDList.getEntity()==null||responsePDList.getEntity().size()==0){
			//原房间状态变为“可售”
			roomUpdateDto.setRoomStatus(RoomStatusEnum.VENDIBILITY.getNo());
		}else{
			roomUpdateDto.setRoomStatus(RoomStatusEnum.RESERVE.getNo());//认筹

		}
		Response<Integer> responseProjctRoomDto=getProjectRoomServiceFacade().updateByPrimaryKey(roomUpdateDto, true);
		if(!responseProjctRoomDto.isSuccess()){
			throw new RuntimeException("房间状态为可售出错");
		}
	}
	
	private void addRoomChangeHistory(Signed oldSigned,ProjectRoom oldRoom,Long signedId){
		RoomChangeHistoryDto changeDto=new RoomChangeHistoryDto();
		changeDto.setRoomId(oldSigned.getRoomId());
		changeDto.setBusinessDynamics("签约换房");
		changeDto.setBusinessHref("/marketing/changeroom/changeDetail?id="+signedId);
		changeDto.setRemark("房态由【"+RoomStatusEnum.getByNo(oldRoom.getRoomStatus()).getDes()+"】转为【"+RoomStatusEnum.VENDIBILITY.getDes()+"】");
		changeDto.setMerchantId(oldSigned.getMerchantId());
		changeDto.setAccessCode(oldSigned.getAccessCode());
		changeDto.setCreateUserId(oldSigned.getCreateUserId());
		changeDto.setUserCode(oldSigned.getUserCode());
		changeDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		changeDto.setUpdateUserId(oldSigned.getUpdateUserId());
		changeDto.setUpdateTime(Calendar.getInstance().getTime());
		Response<RoomChangeHistoryDto> rchSaveResponse = getRoomChangeHistoryServiceFacade().save(changeDto);
		if(!rchSaveResponse.isSuccess()){
			throw new RuntimeException(rchSaveResponse.getResultMessage());
		}
	}
	
	private SignedDto copyOldSigned(Signed oldSigned){
		SignedDto signedUpdateDto=new SignedDto();
		BeanUtil.convert2T(signedUpdateDto, oldSigned);
		signedUpdateDto.setBusinessStatus(BusinessStatusEnum.HAVEWARDS.getNo());
		signedUpdateDto.setBusinessSecStatus(BusinessStatusEnum.HAVEWARDS.getNo());
		signedUpdateDto.setCheckDate(new Date());
		signedUpdateDto.setId(null);
		signedUpdateDto.setOldSignedId(oldSigned.getId());
		Response<SignedDto> addResponse=getSignedServiceFacade().save(signedUpdateDto);
		if(!addResponse.isSuccess()){
			throw new RuntimeException(addResponse.getResultMessage());
		}
		return addResponse.getEntity();
	}
	
	private NeedReceiveRefundDto addNeedReceiveRefundDto(SignedDto copySigned,HaveReceiveRefund hrr){
		NeedReceiveRefundDto needRefundObject=new NeedReceiveRefundDto();
		needRefundObject.setRelationId(copySigned.getId());
		needRefundObject.setBusinessType("2");
		needRefundObject.setCustomerId(copySigned.getCustomerId());
		needRefundObject.setRoomId(copySigned.getRoomId());
		needRefundObject.setStatus("0");
		needRefundObject.setPostponedStatus("0");
		needRefundObject.setRemark("签约换房退款");
		needRefundObject.setMerchantId(copySigned.getMerchantId());
		needRefundObject.setUserCode(copySigned.getUserCode());
		needRefundObject.setAccessCode(copySigned.getAccessCode());
		needRefundObject.setCreateUserId(copySigned.getCreateUserId());
		needRefundObject.setDelFlag("0");
		needRefundObject.setUpdateUserId(copySigned.getUpdateUserId());
		needRefundObject.setUpdateTime(new Date());
		//设置单据类型为待退款
		needRefundObject.setDocType("1");
		//设置待退款金额
		needRefundObject.setTotalReceivablesAmount(hrr.getRealAmount());
		//设置放款类型
		if(hrr.getHousingFundType().indexOf("装修款") < 0) {
			needRefundObject.setHousingFundType(HousingFundTypeEnum.FUNDTYPE_4.getNo());
		} else {
			needRefundObject.setHousingFundType(HousingFundTypeEnum.FUNDTYPE_34.getNo());
		}
		//设置业务标志
		needRefundObject.setBusinessFlag(BusinessFlagEnum.BUSINESSFLAG_8.getNo());
		
		Response<NeedReceiveRefundDto> response=getNeedReceiveRefundServiceFacade().save(needRefundObject);
		if(!response.isSuccess()){
			throw new RuntimeException("签约换房生成待退款失败");
		}
		return response.getEntity();
	}
	
	private void handleOldSignedMoney(ResponseList<HaveReceiveRefund> havResponseList, SignedDto copySigned){
		//原签约已收款转化为复制签约的应退款和已退款
		for(HaveReceiveRefund hrr : havResponseList.getEntity()){
			//生成应退款
			NeedReceiveRefundDto needReceiveRefundDto=addNeedReceiveRefundDto(copySigned,hrr);
			//生成已退款
			HaveReceiveRefundDto addDto=new HaveReceiveRefundDto();
			BeanUtil.convert2T(addDto, hrr);
			addDto.setId(null);
			//设置签约ID
			addDto.setRelationId(copySigned.getId());
			//设置应收款ID
			addDto.setReceivablesId(needReceiveRefundDto.getId());
			//设置为已退款
			addDto.setDocType(DocTypeEnum.REFUND.getNo());
			//设置放款类型
			if(hrr.getHousingFundType().indexOf("装修款") < 0) {
				addDto.setHousingFundType(HousingFundTypeEnum.FUNDTYPE_4.getNo());
			} else {
				addDto.setHousingFundType(HousingFundTypeEnum.FUNDTYPE_34.getNo());
			}
			//由于需要记录历史金额，因此设置退款日期为当前时间（20190102 jzliu）
			addDto.setStatementDate(new Date());
			//设置业务标志
			addDto.setBusinessFlag(BusinessFlagEnum.BUSINESSFLAG_8.getNo());
			Response<HaveReceiveRefundDto> saveRespone=getHaveReceiveRefundServiceFacade().save(addDto);
			if(!saveRespone.isSuccess()){
				throw new RuntimeException(saveRespone.getResultMessage());
			}
		}
	}
	
	private void changeCustomerStatus(Long customerId){
		/**
		 * 查询客户业务状态，并同步更新客户状态
		 */
		CustomerServiceFacade customerServiceFacade = getCustomerServiceFacade();
		String busStatus = customerServiceFacade.queryCustomerBusiness(customerId);
		CustomerDto cusDto = new CustomerDto();
		cusDto.setId(customerId);
		if(busStatus != null){
			cusDto.setCustomerStatus(CustomerStatusEnum.getByDescription(busStatus).getNo());
			Response<Integer> responseCusDto = customerServiceFacade.updateByPrimaryKey(cusDto, true);
			if(!responseCusDto.isSuccess()){
				throw new RuntimeException("客户状态更新出错");
			}
		}else{
			Response<Customer> customerEntity = customerServiceFacade.findById(customerId);
			if(customerEntity.getEntity().getCustomerStatusBk() == null){
				cusDto.setCustomerStatus(CustomerStatusEnum.VISIT.getNo());
			}else{
				cusDto.setCustomerStatus(customerEntity.getEntity().getCustomerStatusBk());
			}
			Response<Integer> responseCusDto = customerServiceFacade.updateByPrimaryKey(cusDto, true);
			if(!responseCusDto.isSuccess()){
				throw new RuntimeException("客户状态更新出错");
			}
		}
	}
	
	private void notice(Long oldSignedId,String processInstanceId){
		/**
		 * （签约换房审核通过）推送消息到app
		 * @author ny
//		 * @param param noticeType 提醒类型, noticeBusinessId 业务主键Id
		 * @return 【${auditStatus}】房号：${roomName}；客户：${customer};
		 */
		NoticeEntity noticeEntity = new NoticeEntity();
		noticeEntity.setNoticeBusinessId(oldSignedId);
		noticeEntity.setNoticeType("8");
		noticeEntity.setProcessInstanceId(processInstanceId);
		getSignedChangeHouseNoticeFacade().createSignedChangeHouseNotice(noticeEntity);
	}
	
	
    private void handleNewSigned(Signed newSigned){
    	SignedDto updateDto = new SignedDto();
		updateDto.setId(newSigned.getId());
		updateDto.setAuditStatus(AuditStatusEnum.SUCCESS.getNo());
		updateDto.setCheckDate(new Date());
		getSignedServiceFacade().updateByPrimaryKey(updateDto, true);
		
		saveNeedReceive(newSigned);
		
		//2.记录房源变更记录
		RoomChangeHistoryDto dto=new RoomChangeHistoryDto();
		dto.setRoomId(newSigned.getRoomId());
		dto.setBusinessDynamics("签约");
		dto.setRemark("房源由【可售】转为【签约】");
		if(newSigned.getSubscribeId()!=null&&!newSigned.getSubscribeId().equals("")){
			dto.setRemark("房源由【认购】转为【签约】");
		}else if(newSigned.getPayDepositId()!=null&&!newSigned.getPayDepositId().equals("")){
			dto.setRemark("房源由【小定】转为【签约】");
		}
		dto.setBusinessHref("/customer/signed/toView?id="+newSigned.getId()+"&returnUrl=,marketing,room,index");
		dto.setMerchantId(newSigned.getMerchantId());
		dto.setAccessCode(newSigned.getAccessCode());
		dto.setCreateUserId(newSigned.getCreateUserId());
		dto.setUserCode(newSigned.getUserCode());
		dto.setDelFlag("0");
		dto.setUpdateUserId(newSigned.getUpdateUserId());
		dto.setUpdateTime(new Date());
		Response<RoomChangeHistoryDto> rchSaveResponse=getRoomChangeHistoryServiceFacade().save(dto);
		if(!rchSaveResponse.isSuccess()){
			throw new RuntimeException(rchSaveResponse.getResultMessage());
		}
		
		//3.查询签约应收并生成按揭记录
		NeedReceiveRefundDto needReceiveRefundDto=new NeedReceiveRefundDto();
		needReceiveRefundDto.setDocType("0");
		needReceiveRefundDto.setBusinessType("2");
		needReceiveRefundDto.setRelationId(newSigned.getId());
		ResponseList<NeedReceiveRefund> responseList=getNeedReceiveRefundServiceFacade().findByDto(needReceiveRefundDto);
		if(null!=responseList && responseList.isSuccess() && null!=responseList.getEntity()){
			MortgageRecordServiceFacade mortgageRecordServiceFacade=getMortgageRecordServiceFacade();
			CustomerServiceFacade customerServiceFacade=getCustomerServiceFacade();
			for(NeedReceiveRefund nff : responseList.getEntity()){
				if(nff.getPaymentMethod().equals(PaymentMethodEnum.LUMP_SUM.getNo()) || nff.getPaymentMethod().equals(PaymentMethodEnum.INSTALLMENT_PAYMENT.getNo())){
					continue;
				}
				String housingFundTyp=nff.getHousingFundType();
				if(housingFundTyp.equals(HousingFundTypeEnum.FUNDTYPE_10.getNo()) || housingFundTyp.equals(HousingFundTypeEnum.FUNDTYPE_17.getNo()) || housingFundTyp.equals(HousingFundTypeEnum.FUNDTYPE_6.getNo())){
					continue;
				}
				MortgageRecordDto mortgageRecordDto=new MortgageRecordDto();
				mortgageRecordDto.setNeedId(nff.getId());
				mortgageRecordDto.setSignedId(newSigned.getId());
				mortgageRecordDto.setRoomId(newSigned.getRoomId());
				mortgageRecordDto.setCustomerId(newSigned.getCustomerId());
				mortgageRecordDto.setProjectId(newSigned.getProjectId());
				mortgageRecordDto.setBusinessFlag(nff.getBusinessFlag());
				mortgageRecordDto.setHousingFundType(nff.getHousingFundType());
				Response<ProjectRoom> projectRoom=getProjectRoomServiceFacade().findById(newSigned.getRoomId());
				if(projectRoom.isSuccess() && null!=projectRoom.getEntity()){
					mortgageRecordDto.setRoomName(projectRoom.getEntity().getCombinedName());
				}else{
					mortgageRecordDto.setRoomName("未知");
				}
				Response<Customer> customerResponse=customerServiceFacade.findById(newSigned.getCustomerId());
				if(customerResponse.isSuccess() && null!=customerResponse.getEntity()){
					mortgageRecordDto.setCustomerName(customerResponse.getEntity().getCustomerName());
				}else{
					mortgageRecordDto.setCustomerName("未知");
				}
				
				mortgageRecordDto.setSignedDate(newSigned.getDidTime());
				mortgageRecordDto.setSignAmount(newSigned.getSignAmount());
				//按揭金额
				mortgageRecordDto.setMortgageAmount(nff.getTotalReceivablesAmount());
				mortgageRecordDto.setMortgageReceivedStatus("0");
				mortgageRecordDto.setMortgageCheckStatus("0");
				mortgageRecordDto.setProcessStatus("0");
				
				mortgageRecordDto.setMerchantId(newSigned.getMerchantId());
				mortgageRecordDto.setAccessCode(newSigned.getAccessCode());
				mortgageRecordDto.setCreateUserId(newSigned.getCreateUserId());
				mortgageRecordDto.setUserCode(newSigned.getUserCode());
				mortgageRecordDto.setDelFlag("0");
				mortgageRecordDto.setUpdateUserId(newSigned.getUpdateUserId());
				mortgageRecordDto.setUpdateTime(new Date());
				mortgageRecordDto.setReceivablesFunds(nff.getReceivablesFunds());
				Response<MortgageRecordDto> response=mortgageRecordServiceFacade.save(mortgageRecordDto);
				if(!response.isSuccess()){
	    			throw new RuntimeException(response.getResultMessage());
	    		}
			}
		}

    }
    
    private void saveNeedReceive(Signed signed) {
		String extraInformation=signed.getExtraInformation();
		if(StringUtils.isBlank(extraInformation)){
			return;
		}
		JSONObject object=JSON.parseObject(extraInformation);
		JSONArray needReceive = object.getJSONArray("paymentDetails");
		if (null != needReceive && needReceive.size() > 0) {
			for (int i = 0; i < needReceive.size(); i++) {
				NeedReceiveRefundDto needReceiveRefundDto = JSONObject
						.parseObject(needReceive.getJSONObject(i).toJSONString(), NeedReceiveRefundDto.class);
				needReceiveRefundDto.setRelationId(signed.getId());
				needReceiveRefundDto.setBusinessType("2");
				needReceiveRefundDto.setCustomerId(signed.getCustomerId());
				needReceiveRefundDto.setRoomId(signed.getRoomId());
				needReceiveRefundDto.setStatus("1");
				needReceiveRefundDto.setPostponedStatus("0");
				needReceiveRefundDto.setDocType("0");
				needReceiveRefundDto.setRemark("签约收款");
				needReceiveRefundDto.setMerchantId(signed.getMerchantId());
				needReceiveRefundDto
						.setPaymentMethod(signed.getPaymentMethod());
				needReceiveRefundDto.setUserCode(signed.getUserCode());
				needReceiveRefundDto.setAccessCode(signed.getAccessCode());
				needReceiveRefundDto.setCreateUserId(signed.getCreateUserId());
				needReceiveRefundDto.setDelFlag("0");
				needReceiveRefundDto.setUpdateUserId(signed.getUpdateUserId());
				needReceiveRefundDto.setUpdateTime(new Date());
				Response<NeedReceiveRefundDto> nrrdSaveResponse=getNeedReceiveRefundServiceFacade().save(needReceiveRefundDto);
				/*NeedReceiveRefundDto nrrdSaveResponse = needReceiveRefundService
						.create(needReceiveRefundDto);*/
				if (!nrrdSaveResponse.isSuccess()) {
					throw new RuntimeException("保存签约应收信息错误");
				}
			}
		}
	}
	
	/**
	 * 修改未结清的原签约待收款为已结清
	 * @param id
	 */
	private void setOldNeedStatus(Long id){
		NeedReceiveRefundDto dto = new NeedReceiveRefundDto();
		dto.setRelationId(id);
		dto.setStatus(NeedStatusEnum.NO.getNo());
		dto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		dto.setDocType(DocTypeEnum.COLLECTION.getNo());
		dto.setBusinessType(BusinessTypeEnum.SIGNED.getNo());
		ResponseList<NeedReceiveRefund> resList = getNeedReceiveRefundServiceFacade().findByDto(dto);
		if(!resList.isSuccess()){
			return;
		}
		if(resList.getEntity() == null){
			return;
		}
		for(NeedReceiveRefund need : resList.getEntity()){
			NeedReceiveRefundDto entity = new NeedReceiveRefundDto();
			entity.setStatus(NeedStatusEnum.YES.getNo());
			entity.setId(need.getId());
			getNeedReceiveRefundServiceFacade().updateByPrimaryKey(entity, true);
		}
	}
	/**
	 * 计算新签约的已收款
	 * @param havResponseList
	 * @param newSigendId
	 */
	private void calculationNewHaveReceive(ResponseList<HaveReceiveRefund> havResponseList, Long newSigendId){
		//原签约已收款总金额
		BigDecimal realAmount = new BigDecimal("0");
		for(HaveReceiveRefund hrr : havResponseList.getEntity()){
			realAmount = realAmount.add(hrr.getRealAmount());
		}
		
		//查询新签约未收款
		NeedReceiveRefundDto dto = new NeedReceiveRefundDto();
		dto.setRelationId(newSigendId);
		dto.setDocType(DocTypeEnum.COLLECTION.getNo());
		dto.setBusinessType(BusinessTypeEnum.SIGNED.getNo());
		dto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		ResponseList<NeedReceiveRefund> needResponseList = getNeedReceiveRefundServiceFacade().findByDto(dto);
		if(!needResponseList.isSuccess() || null == needResponseList.getEntity()){
			return;
		}
		for(NeedReceiveRefund need : needResponseList.getEntity()){
			//当原签约剩余金额小于或等于0时，退出循环
			if(realAmount.compareTo(new BigDecimal("0")) <= 0){
				break;
			}
			//单笔应收金额
			BigDecimal needAmount = need.getTotalReceivablesAmount();
			if(realAmount.compareTo(needAmount) >= 0){
				//当原签约已收总额大于新签约单笔未收款时，新签约已收款等于新签约单笔未收款
				saveNewHaveReceive(need, needAmount, "0");
			}else{
				//当原签约已收总额小于新签约单笔未收款时，新签约已收款等于原签约已收款
				saveNewHaveReceive(need, realAmount, "1");
			}
			//计算原签约剩余已收金额
			realAmount = realAmount.subtract(needAmount);
		}
	}
	/**
	 * 查询原签约已收款
	 * @param id
	 * @return
	 */
	private ResponseList<HaveReceiveRefund> getOldHaveReceiveRefund(Long id){
		HaveReceiveRefundDto haveReceiveRefundDto = new HaveReceiveRefundDto();
		haveReceiveRefundDto.setRelationId(id);
		haveReceiveRefundDto.setReceivablesType("2");
		haveReceiveRefundDto.setDocType(DocTypeEnum.COLLECTION.getNo());
		ResponseList<HaveReceiveRefund> havResponseList = getHaveReceiveRefundServiceFacade().findByDto(haveReceiveRefundDto);
		return havResponseList;
	}
	/**
	 * 保存新签约收款记录
	 * @param need
	 * @param realAmount 已收金额
	 */
	private void saveNewHaveReceive(NeedReceiveRefund need, BigDecimal realAmount, String status){
		//添加收款记录
		HaveReceiveRefundDto haveReceiveRefundDto = new HaveReceiveRefundDto();
		haveReceiveRefundDto.setReceivablesId(need.getId()); 
		haveReceiveRefundDto.setRelationId(need.getRelationId()); 
		haveReceiveRefundDto.setDeductibleAmount(new BigDecimal(0)); //抵扣金额
		haveReceiveRefundDto.setRealAmount(realAmount); //已收金额
		haveReceiveRefundDto.setReChecked("0"); //复核状态
		haveReceiveRefundDto.setPaymentMethod(need.getPaymentMethod()); //支付方式
		haveReceiveRefundDto.setReceivablesFunds(need.getReceivablesFunds()); //付款方式
		haveReceiveRefundDto.setReceivablesType(need.getBusinessType()); //业务类型
		haveReceiveRefundDto.setTransferStatus(TransferStatusEnum.NORMAL.getNo()); //非内部转账
		haveReceiveRefundDto.setCustomerId(need.getCustomerId());
		haveReceiveRefundDto.setRoomId(need.getRoomId());
		haveReceiveRefundDto.setReceivablesDate(need.getReceivablesDate()); //应收日期
		haveReceiveRefundDto.setHousingFundType(need.getHousingFundType()); //房款类型
		haveReceiveRefundDto.setBusinessFlag(need.getBusinessFlag()); //业务标志
		haveReceiveRefundDto.setDocType(DocTypeEnum.COLLECTION.getNo()); //待收款
		haveReceiveRefundDto.setStatementDate(Calendar.getInstance().getTime()); //结算日期
		haveReceiveRefundDto.setRemark(need.getRemark()); //备注
		haveReceiveRefundDto.setMerchantId(need.getMerchantId());
		haveReceiveRefundDto.setAccessCode(need.getAccessCode());
		haveReceiveRefundDto.setUserCode(need.getUserCode());
		haveReceiveRefundDto.setCreateUserId(need.getCreateUserId());
		haveReceiveRefundDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
		
		Response<HaveReceiveRefundDto> res = getHaveReceiveRefundServiceFacade().save(haveReceiveRefundDto);
		if(res.isSuccess()){
			//当新签约的未收款记录已结清时，修改未收款为已收
			if("0".equals(status)){
				editNewNeedToHave(need.getId());
			}
		}
	}
	/**
	 * 修改新签约的未收款为已收
	 * @param id
	 */
	private void editNewNeedToHave(Long id){
		NeedReceiveRefundDto dto = new NeedReceiveRefundDto();
		dto.setId(id);
		dto.setStatus("0"); //是否结清
		getNeedReceiveRefundServiceFacade().updateByPrimaryKey(dto, true);
	}
	/**
	 * 审核通过后，修改新签约记录为已通过
	 * @param id
	 */
	private void updateNewSingedAuditStatus(Long id){
		SignedDto dto = new SignedDto();
		dto.setId(id);
		dto.setAuditStatus(AuditStatusEnum.SUCCESS.getNo());
		getSignedServiceFacade().updateByPrimaryKey(dto, true);
	}
	
	public BusinessAbnorma businessById(Long id){
		BusinessAbnorma ba = new BusinessAbnorma();
		BusinessAbnormaDto babDto = new BusinessAbnormaDto(); 
		babDto.setBusinessId(new Long(id));
		babDto.setBusinessType(BusinessAbnormaEnum.BusinessAbnorma_3.getNo());
		babDto.setAuditStatus(AuditStatusEnum.AUDIT.getNo()); //只获取审核中的流程信息
		babDto.setOrders(" t.create_time desc ");
		ResponseList<BusinessAbnorma> busineList = getbusinessAbnormaServiceFacade().findByDto(babDto);
		if(busineList.isSuccess()&&busineList.getEntity()!=null){
			ba = busineList.getEntity().get(0);
			return ba;
		}
		return ba;
	}
	
	/**
	 * 前置判断,审核记录是否已经提交,防止重复提交
	 * 产生原因: 提交审核,后台处理中时,刷新页面再次提交审核,会重复
	 * true: 可继续执行
	 * false: 不可执行
	 */
	public boolean checkAuditCommit(BusinessAbnorma entity) {
		// 业务数据为null时,默认通过.为了不改变老业务,不影响流程正常行走
		if (null == entity) {
			return true;
		}
		return getActcommitLogService().checkActCommit(entity.getAuditStatus(), entity.getMerchantId(), entity.getId(),
				entity.getProcInstId(), "签约换房", "PC");
	}
	
	/**
	 * 2019-02增加
	 * 签约换房，退原认购逻辑
	 * junze.liu
	 */
	private String subscribeRetreat(Long roomId, Long customerId) {
		//查询认购记录
		SubscribeDto subscribeDto = new SubscribeDto();
		subscribeDto.setM_auditStatus(" and t.audit_status = '3' and t.business_status = '2' and t.business_sec_status is null");
		subscribeDto.setRoomId(roomId);
		subscribeDto.setCustomerId(customerId);
		ResponseList<Subscribe> responseList = getSubscribeServiceFacade().findByDtoJ(subscribeDto);
		//不是认购转签约时，直接返回
		if(responseList.getEntity() == null || responseList.getEntity().size() == 0){
			return null;
		}
		//是认购转签约时,执行退认购逻辑
		Subscribe subscribe = (Subscribe)responseList.getEntity().get(0);
		//修改认购记录为退认购
		SubscribeDto updatePddDto = new SubscribeDto();
		updatePddDto.setId(subscribe.getId());
		updatePddDto.setBusinessStatus(SubscribeBusinessStatusEnum.SUBSCRIBE.getNo());
		updatePddDto.setBusinessSecStatus("5");
		updatePddDto.setIsCkeckOut("2"); //标识签约换房
		Response<Integer> responseUudate = getSubscribeServiceFacade().updateByPrimaryKey(updatePddDto, true);
		
		//生成新的认购记录 认购状态为退认购
		SubscribeDto createNewSubscribe = new SubscribeDto();
		BeanUtil.convert2T(createNewSubscribe, subscribe);
		createNewSubscribe.setBusinessStatus("5");
		createNewSubscribe.setBusinessSecStatus("5");
		createNewSubscribe.setIsCkeckOut("2"); //标识签约换房
		SubscribeDto addSub = getSubscribeServiceFacade().save(createNewSubscribe).getEntity();
		
		return null;
	}
	
	private ActCommitLogService getActcommitLogService(){
		return (ActCommitLogService)SpringWebContextUtil.getApplicationContext().getBean("actCommitLogService");
	}
	
	private CustomerServiceFacade getCustomerServiceFacade(){
		return (CustomerServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("customerServiceFacade");
	}
	
	private SignedChangeHouseNoticeFacade getSignedChangeHouseNoticeFacade(){
		return (SignedChangeHouseNoticeFacade)SpringWebContextUtil.getApplicationContext().getBean("signedChangeHouseNoticeFacade");
	}
	
	private ActivitiProcessServiceImpl getActivitiProcessServiceImpl(){
		return (ActivitiProcessServiceImpl)SpringWebContextUtil.getApplicationContext().getBean("activitiProcessServiceImpl");
	}

	private RoomChangeHistoryServiceFacade getRoomChangeHistoryServiceFacade(){
		return (RoomChangeHistoryServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("roomChangeHistoryServiceFacade");
	}
	
	/*private SubscribeServiceFacade getSubscribeServiceFacade(){
		return (SubscribeServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("subscribeServiceFacade");
	}*/
	
	private ProjectRoomServiceFacade getProjectRoomServiceFacade(){
		return (ProjectRoomServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("projectRoomServiceFacade");
	}
	
	private BusinessAbnormaServiceFacade getbusinessAbnormaServiceFacade(){
		return (BusinessAbnormaServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("businessAbnormaServiceFacade");
	}
	
	private SignedServiceFacade getSignedServiceFacade(){
		return (SignedServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("signedServiceFacade");
	}
	
	private PayDepositServiceFacade getPayDepositServiceFacade(){
		return (PayDepositServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("payDepositServiceFacade");
	}
	
	private HaveReceiveRefundServiceFacade getHaveReceiveRefundServiceFacade(){
		return (HaveReceiveRefundServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("haveReceiveRefundServiceFacade");
	}
	
	private NeedReceiveRefundServiceFacade getNeedReceiveRefundServiceFacade(){
		return (NeedReceiveRefundServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("needReceiveRefundServiceFacade");
	}
	
	private MortgageRecordServiceFacade getMortgageRecordServiceFacade(){
		return (MortgageRecordServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("mortgageRecordServiceFacade");
	}
	private LevelProjectDataService getLevelProjectDataService(){
		return (LevelProjectDataService)SpringWebContextUtil.getApplicationContext().getBean("levelProjectDataService");
	}
	private PmoPushService getPmoPushService(){
		return (PmoPushService)SpringWebContextUtil.getApplicationContext().getBean("pmoPushService");
	}
	
	private SubscribeServiceFacade getSubscribeServiceFacade(){
		return (SubscribeServiceFacade)SpringWebContextUtil.getApplicationContext().getBean("subscribeServiceFacade");
	}

	private ChannelSendHttpMessageService getChannelSendHttpMessageService(){
		return (ChannelSendHttpMessageService)SpringWebContextUtil.getApplicationContext().getBean("channelSendHttpMessageService");
	}
}
